/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT,
 * THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package com.lineage.server.model.item;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import com.lineage.server.model.L1PolyMorph;
import com.lineage.server.model.Instance.L1ItemInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.item.etcitem.UsePotion_AddHp;
import com.lineage.server.model.item.etcitem.UsePotion_AddMp;
import com.lineage.server.model.item.etcitem.UsePotion_Blind;
import com.lineage.server.model.item.etcitem.UsePotion_RestorationMp;
import com.lineage.server.model.item.etcitem.UsePotion_Wisdom;
import com.lineage.server.packetserver.S_SystemMessage;
import com.lineage.server.utils.collections.Maps;

/**
 * Class <code>L1ItemUseXml</code> 道具类使用(测试).
 * 
 * @author jrwz
 * @version 2012-6-18上午10:36:02
 * @see com.lineage.server.model.item
 * @since JDK1.7
 */
@XmlAccessorType(XmlAccessType.FIELD)
public final class L1ItemUseXml {

    /**
     * 道具使用效果.
     */
    @XmlAccessorType(XmlAccessType.FIELD)
    private static class Effect {
        /** 是否删除. */
        @XmlAttribute(name = "是否删除")
        private final Boolean isRemove = false;
        /** 是否解毒. */
        @XmlAttribute(name = "是否解毒")
        private final Boolean isCurePoison = false;
        /** 动画效果. */
        @XmlAttribute(name = "动画编号")
        private int gfx;
        /** 动画目标. */
        @XmlAttribute(name = "动画目标")
        private byte gfxTarget;
        /** 技能效果时间:闇盲咒术. */
        @XmlAttribute(name = "技能效果时间_闇盲咒术")
        private int skillEffectCurseBlindTime;
        /** 加血量. */
        @XmlAttribute(name = "加血")
        private int addHp;
        /** 加魔量. */
        @XmlAttribute(name = "加魔")
        private int addMp;
        /** 增加魔攻时间. */
        @XmlAttribute(name = "增加魔攻时间")
        private int addSpTime;
        /** 回魔时间. */
        @XmlAttribute(name = "回魔时间")
        private int reMpTime;
        /** 变身编号. */
        @XmlAttribute(name = "变身编号")
        private int polyId;
        /** 变身时间. */
        @XmlAttribute(name = "变身时间")
        private int polyTime;

        /**
         * 取得加血量.
         * 
         * @return 加血量
         */
        public int getEffectAddHp() {
            return this.addHp;
        }

        /**
         * 取得加魔量.
         * 
         * @return 加魔量
         */
        public int getEffectAddMp() {
            return this.addMp;
        }

        /**
         * 取得增加魔攻时间.
         * 
         * @return 增加魔攻时间
         */
        public int getEffectAddSpTime() {
            return this.addSpTime;
        }

        /**
         * 取得技能效果时间:闇盲咒术.
         * 
         * @return 技能效果时间
         */
        public int getEffectCurseBlindTime() {
            return this.skillEffectCurseBlindTime;
        }

        /**
         * 取得动画效果.
         * 
         * @return 效果编号
         */
        public int getEffectGfx() {
            return this.gfx;
        }

        /**
         * 取得动画目标.
         * 
         * @return 动画目标(0:自己看到、1:周围人看到、2:全部可见)
         */
        public byte getEffectGfxTarget() {
            return this.gfxTarget;
        }

        /**
         * 取得回魔时间.
         * 
         * @return 回魔时间
         */
        public int getEffectReMpTime() {
            return this.reMpTime;
        }

        /**
         * 取得变身编号.
         * 
         * @return 变身编号
         */
        public int getPolyId() {
            return this.polyId;
        }

        /**
         * 取得变身时间.
         * 
         * @return 变身时间
         */
        public int getPolyTime() {
            return this.polyTime;
        }

        /**
         * 是否解毒.
         * 
         * @return true or false
         */
        public Boolean isCurePoison() {
            return this.isCurePoison;
        }

        /**
         * 是否删除道具.
         * 
         * @return true or false
         */
        public Boolean isRemove() {
            return this.isRemove;
        }
    }

    /**
     * 道具列表.
     */
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlRootElement(name = "ItemUseList")
    private static class ItemUseList implements Iterable<L1ItemUseXml> {
        /** 列表. */
        @XmlElement(name = "ItemUse")
        private List<L1ItemUseXml> list;

        // 返回一个迭代的T类型的元素集
        @Override
        public Iterator<L1ItemUseXml> iterator() {
            return this.list.iterator();
        }
    }

    /** 可使用职业. */
    private static enum PROFESSION {
        /** 王族. */
        王族,
        /** 骑士. */
        骑士,
        /** 法师. */
        法师,
        /** 精灵. */
        精灵,
        /** 黑暗精灵. */
        黑暗精灵,
        /** 龙骑士. */
        龙骑士,
        /** 幻术师. */
        幻术师
    }

    /** 道具的使用类型. */
    private static enum TYPE {
        /** 防具. */
        ARMOR,
        /** 道具. */
        ETCITEM,
        /** 武器. */
        WEAPON
    }

    /** 提示信息. */
    private static final Logger LOG = Logger.getLogger(L1ItemUseXml.class
            .getName());
    /** XML档路径. */
    private static final String PATH = "./data/xml/Item/ItemUse.xml";
    /** 数据集合. */
    private static final Map<Integer, L1ItemUseXml> DATA_MAP = Maps.newMap();

    /**
     * 取得指定ID(集合内).
     * 
     * @param id
     *            - 道具的ItemId
     * @return 没有找到则返回null
     */
    public static L1ItemUseXml get(final int id) {
        return DATA_MAP.get(id);
    }

    /**
     * 加载.
     */
    public static void load() {
        try {
            final JAXBContext context = JAXBContext
                    .newInstance(L1ItemUseXml.ItemUseList.class);
            final Unmarshaller um = context.createUnmarshaller();
            final File file = new File(PATH);
            final ItemUseList list = (ItemUseList) um.unmarshal(file);
            for (final L1ItemUseXml each : list) {
                each.init();
                DATA_MAP.put(each.getItemId(), each);
            }
        } catch (final Exception e) {
            LOG.log(Level.SEVERE, PATH + " 文件载入失败.", e);
            System.exit(0);
        }
    }

    /** 道具编号. */
    @XmlAttribute(name = "ItemId")
    private int itemId;

    /** 使用类型. */
    @XmlAttribute(name = "Type")
    private TYPE type;
    /** 可用职业. */
    @XmlAttribute(name = "可用职业")
    private PROFESSION profession;

    /** 道具效果:药水. */
    @XmlElement(name = "Effect")
    private CopyOnWriteArrayList<Effect> itemEffect;

    /**
     * 取得道具效果.
     * 
     * @return 道具效果
     */
    private List<Effect> getEffect() {
        return this.itemEffect;
    }

    /**
     * 取得道具编号.
     * 
     * @return 道具编号
     */
    private int getItemId() {
        return this.itemId;
    }

    /**
     * 取得可用职业.
     * 
     * @return 职业
     */
    private PROFESSION getProfession() {
        return this.profession;
    }

    /**
     * 取得使用类型.
     * 
     * @return 类型
     */
    private TYPE getType() {
        return this.type;
    }

    /**
     * 初始化.
     */
    private void init() {
        // TODO
    }

    /**
     * 使用道具.
     * 
     * @param pc
     *            - 对象
     * @param item
     *            - 道具
     * @return 无论结果如何始终返回true
     */
    public boolean useItem(final L1PcInstance pc, final L1ItemInstance item) {
        System.out.println("Xml执行.");
        if (this.getProfession() != null) {
            boolean isUse = false;
            if (this.getProfession().equals(PROFESSION.王族)) {
                if (!pc.isCrown()) {
                    isUse = true;
                }
            } else if (this.getProfession().equals(PROFESSION.骑士)) {
                if (!pc.isKnight()) {
                    isUse = true;
                }
            } else if (this.getProfession().equals(PROFESSION.法师)) {
                if (!pc.isWizard()) {
                    isUse = true;
                }
            } else if (this.getProfession().equals(PROFESSION.精灵)) {
                if (!pc.isElf()) {
                    isUse = true;
                }
            } else if (this.getProfession().equals(PROFESSION.黑暗精灵)) {
                if (!pc.isDarkelf()) {
                    isUse = true;
                }
            } else if (this.getProfession().equals(PROFESSION.龙骑士)) {
                if (!pc.isDragonKnight()) {
                    isUse = true;
                }
            } else if (this.getProfession().equals(PROFESSION.幻术师)) {
                if (!pc.isIllusionist()) {
                    isUse = true;
                }
            }
            if (isUse) {
                pc.sendPackets(new S_SystemMessage("\\f1你的职业无法使用此物品。"));
            }
        } else if (this.getType().equals(TYPE.ETCITEM)) { // 道具
            for (final Effect each : this.getEffect()) {
                final int gfxId = each.getEffectGfx();
                if (gfxId > 0) {
                    final byte gfxTarget = each.getEffectGfxTarget();
                    SkillEffectGfx.get().execute(pc, gfxId, gfxTarget);
                }
                final int addHp = each.getEffectAddHp();
                if (addHp > 0) {
                    UsePotion_AddHp.get().useItem(pc, item, 0, addHp, 0, 0);
                }
                final int addMp = each.getEffectAddMp();
                if (addMp > 0) {
                    UsePotion_AddMp.get().useItem(pc, item, 0, addMp, 0, 0);
                }
                final int addSpTime = each.getEffectAddSpTime();
                if (addSpTime > 0) {
                    UsePotion_Wisdom.get()
                            .useItem(pc, item, 0, 0, addSpTime, 0);
                }
                final int reMpTime = each.getEffectReMpTime();
                if (reMpTime > 0) {
                    UsePotion_RestorationMp.get().useItem(pc, item, 0, 0,
                            reMpTime, 0);
                }
                final int polyId = each.getPolyId();
                final int polyTime = each.getPolyTime();
                if ((polyId > 0) && (polyTime > 0)) {
                    L1PolyMorph.doPoly(pc, polyId, polyTime,
                            L1PolyMorph.MORPH_BY_ITEMMAGIC);
                }
                final int curseBlindTime = each.getEffectCurseBlindTime();
                if (curseBlindTime > 0) {
                    UsePotion_Blind.get().useItem(pc, item, 0, 0,
                            curseBlindTime, 0);
                }
                final Boolean isCurePoison = each.isCurePoison();
                if (isCurePoison) {
                    pc.curePoison(); // 解毒
                }
                final Boolean flag = each.isRemove();
                if (flag) {
                    pc.getInventory().removeItem(item, 1);
                }
            }
        }
        return true;
    }
}
